package  com.apollographql.apollo.api

import com.apollographql.apollo.api.Executable.Variables
import com.apollographql.apollo.api.json.ApolloJsonElement
import com.apollographql.apollo.api.json.JsonWriter
import okio.IOException

/**
 * Base interface for [Operation] and [Fragment] that have a [Adapter] and [Variables].
 *
 * Fragments cannot be executed against a server but can be executed against the cache.
 */
interface Executable<D: Executable.Data> {
  /**
   * The [Adapter] that maps the server response data to/from generated model class [D].
   *
   * This is the low-level API generated by the compiler. Use [parseJsonResponse] and [composeJsonResponse] extension functions for a higher level API
   */
  fun adapter(): Adapter<D>

  /**
   * Serializes the variables of this operation to a json
   */
  @Throws(IOException::class)
  fun serializeVariables(writer: JsonWriter, customScalarAdapters: CustomScalarAdapters, withDefaultValues: Boolean)

  /**
   * A list of [CompiledSelection]. Used when reading from the cache and/or normalizing a model.
   * Use [com.apollographql.apollo.cache.normalized.ApolloStore.readOperation] for a higher level API
   */
  fun rootField(): CompiledField

  /**
   * Marker interface for generated models
   */
  interface Data

  /**
   * A helper class to hold variables
   *
   * [valueMap] contains all the variables as a Json-like map. Custom scalars are
   * serialized to their json representation (String/Map most of the time).
   * Input objects are serialized to Map<String, Any?>
   */
  class Variables(val valueMap: VariablesJson)
}

/**
 * The variables as a Json representation. If some
 */
typealias VariablesJson = Map<String, ApolloJsonElement>